/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.brainstretch.jsf;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import javax.servlet.http.Part;
import org.brainstretch.ejb.managers.QuizManager;
import org.brainstretch.jsf.util.JsfUtil;
import org.brainstretch.models.User;
import org.brainstretch.models.quizzes.*;
import org.brainstretch.util.FileStorageUtil;
import org.primefaces.event.FileUploadEvent;


/**
 *
 * @author mrodaitis
 */
@ManagedBean
@ViewScoped
public class QuizBuilder implements Serializable{

    
    private static final Pattern extensionPattern = Pattern.compile("(.+\\.)+(.+)");
    private static final String[] audioExtensions = {"aif", "aiff", "mp3", "wav"};
    private static final String[] videoExtensions = {"flv", "fxm"};
    
    private Quiz quiz;    
    private Map<String, UploadedFile> files;
    
    @ManagedProperty("#{userController}")
    UserController userController;
    
    @EJB
    QuizManager quizManager;
    
    private Category[] categories;    
    
    private int currentSet = 0;
    private String currentText;
    private String currentSolution;
    
    
    public String addToSet(){
        Question question = getQuestionFromInput();
        if(question != null){
            quiz.getQuestionSets().get(currentSet).getQuestions().add(question);
        }
        return null;
    }
    
    public String addAsNew(){        
        Question question = getQuestionFromInput();
        if(question != null){
            QuestionSet added = addQuestionSet(question);
        }        
        return null;
    }
    
    public Question getQuestionFromInput(){
        Question question = new Question();
        Clue text = new Clue();
        text.setText(currentText);
        question.getSolution().setText(currentSolution);
        question.setTextClue(text);
        clearFields();
        return question;
    }
    
    private byte[] readFile(Part part) {
		int len = (int) part.getSize();
		byte[] fileBytes = new byte[len];
		try {
			InputStream stream = part.getInputStream();
			int off = 0, read = 0;
			while (read != -1) {
				read = stream.read(fileBytes, off, len - off);
				off += read;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return fileBytes;
    }
    
    private String getFileName(Part part) {
            String fileName = "";
            String contentDisposition = part.getHeader("content-disposition");
            String[] dispositionParts = contentDisposition.split(";");
            for (String partString : dispositionParts) {
                    if (partString.trim().startsWith("filename")) {
                            fileName = partString.substring(partString.indexOf("=") + 1).trim().replace("\"", "");
                    }
            }
            return fileName;
    }
    
    
    private String addFile(String fileName, byte[] contents){
        if(files == null){
            files = new HashMap<String, UploadedFile>();
            for(QuestionSet set: quiz.getQuestionSets()){
                for(Question question: set.getQuestions()){
                    if(question.getMediaClue() != null){
                        UploadedFile existing = new UploadedFile();
                        files.put(question.getMediaClue().getText(), existing);
                    }
                }
            }
        }
        String realName = getRealFileName(fileName);
        files.put(realName, new UploadedFile(contents));
        return realName;
    }
    
    private String getRealFileName(String fileName){
        int append = 1;
        String adjustedName = fileName;
        UploadedFile existingFile = files.get(adjustedName);
        while(existingFile != null){
            adjustedName = FileStorageUtil.appendNumberTo(fileName, append++);
            existingFile = files.get(adjustedName);
        }
        return adjustedName;
    }
    
    
    private void clearFields(){
        currentText = "";
        currentSolution = "";
    }
    
    public QuestionSet addQuestionSet(Question question){
        QuestionSet newSet = new QuestionSet();
        newSet.getQuestions().add(question);
        newSet.setOrdinal(quiz.getQuestionSets().size());
        getQuiz().getQuestionSets().add(newSet);
        return newSet;
    }

    
    public String addQuestion(QuestionSet set){
        set.getQuestions().add(getNewQuestion());        
        return null;
    }
    
    public String removeQuestion(QuestionSet qSet, Question question){
        qSet.getQuestions().remove(question);
        if(qSet.getQuestions().isEmpty()){
            System.out.println(quiz.getQuestionSets().size());
            quiz.getQuestionSets().remove(qSet);
            System.out.println(quiz.getQuestionSets().size());
        }
        return null;
    }
    
    private void addClue(Question question, ClueType clueType){
        Clue clue = new Clue();
        clue.setType(clueType);
        if(clue.getType() == ClueType.Text)
            question.setTextClue(clue);
        else
            question.setMediaClue(clue);
    }
    
    private Question getNewQuestion(){
        Question question = new Question();
        addClue(question, ClueType.Text);
        return question;
    }
    
    
    public String removeClue(Question question, Clue clue){
        if(clue.getType() == ClueType.Text)
            question.setTextClue(null);
        else{
            question.setMediaClue(null);
        }
        return null;
    }

    
    public String createQuiz(){
        quizManager.update(quiz);
        return "home";
    }
    
    public String removeQuestionSet(QuestionSet set){
        quiz.getQuestionSets().remove(set);
        return null;
    }
    
    public Quiz getQuiz(){
        if(quiz == null){
            String quizIdParam = JsfUtil.getRequestParameter("quizId");
            long quizId = -1;
            if(quizIdParam != null){
                try{
                    quizId = Long.parseLong(quizIdParam);
                }catch(NumberFormatException ex){
                    quizId = -1;
                }
            }
            quiz = quizManager.findById(quizId);
            if(quiz == null){
                quiz = quizManager.create(getCurrentUser());
            }
        }
        return quiz;
    }
    
    private User getCurrentUser(){
        return userController.getUser();
    }

    public UserController getUserController() {
        return userController;
    }

    public void setUserController(UserController userController) {
        this.userController = userController;
    }

    public int getCurrentSet() {
        return currentSet;
    }

    public void setCurrentSet(int currentSet) {
        this.currentSet = currentSet;
    }

    public String getCurrentSolution() {
        return currentSolution;
    }

    public void setCurrentSolution(String currentSolution) {
        this.currentSolution = currentSolution;
    }

    public String getCurrentText() {
        return currentText;
    }

    public void setCurrentText(String currentText) {
        this.currentText = currentText;
    }

    public Category[] getCategories() {
        if(categories == null){
            categories = Category.values();
        }
        return categories;
    }

    public void setCategories(Category[] categories) {
        this.categories = categories;
    }
    
    private enum UploadedFileStatus{
        PreExisting, New
    }
    
    private class UploadedFile{
        private UploadedFileStatus status;
        private byte[] content;

        public UploadedFile(byte[] content) {
            this.status = UploadedFileStatus.New;
            this.content = content;
        }

        public UploadedFile() {
            this.status = UploadedFileStatus.PreExisting;
        }

        public byte[] getContent() {
            return content;
        }

        public UploadedFileStatus getStatus() {
            return status;
        }       
    }
    
}
